package com.terry.proxy.socket.impl;

import cn.hutool.core.util.ObjUtil;
import com.terry.proxy.application.cache.DBCache;
import com.terry.proxy.common.Msg;
import com.terry.proxy.socket.ISocketProxyServer;
import com.terry.proxy.util.SocketCreateUtil;
import com.terry.proxy.util.TcpConsumer;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import static com.terry.proxy.application.cache.DBCache.N;
import static com.terry.proxy.common.Msg.*;
import static com.terry.proxy.util.SocketCreateUtil.CID;

/**
 * netty socket代理 服务
 *
 * @author terry
 * @version 1.0
 * @date 2022/12/15 11:07
 */
@Slf4j
@ConditionalOnProperty(name = "proxy.protocol", havingValue = "netty-server")
@Component
public class NettySocketProxyServer extends ISocketProxyServer {

    @Override
    public void openServer() {
        Integer port = Integer.parseInt(DBCache.getConfigByKey(DBCache.CONFIG_SERVER_PORT));
        log.info("服务端启动成功，端口号 {}！", port);
        // 开启服务端
        new SocketCreateUtil().openServerProxy(port, new TcpConsumer<Msg>(null
                , (ctx, msg) -> {
            // 代理服务器读到客户端数据了
            String type = msg.getType();
            switch (type) {
                // 处理代理连接（客户端代理 -> 服务端代理，用于校验客户端、绑定关系、发送隧道绑定消息）
                case PROXY_CONNECT:
                    // clientProxyChannel.put(msg.getHeader().getClientId(), ctx.channel());
                    boolean isSuccess = super.proxyConnect(msg, ctx.channel());
                    if (isSuccess) {
                        clientProxyChannel.put(msg.getHeader().getClientId(), ctx.channel());
                    }
                    break;
                // 处理访客真实服务响应数据（访客客户端 -> 服务端访客，用于响应给真实服务）
                case PROXY_RESPONSE:
                    super.proxyResponse(msg);
                    break;
                // 客户端访客关闭事件（客户端访客服务 -> 服务端访客服务，用于解决 旧http请求bug问题）
                case VISITOR_CLIENT_CLOSE:
                    log.info(" 客户端访客关闭事件（客户端访客服务 -> 服务端访客服务，用于解决 旧http请求bug问题）");
                    super.closeChannel(msg.getHeader().getVisitorId());
                    break;
                default:
                    // 操作有误
                    break;
            }
        }
        , this::handleProxyClose, null).toPipeline());
    }

    public void handleProxyClose(ChannelHandlerContext ctx) {
        System.out.println("onClose");
        String clientId = ctx.channel().attr(CID).get();
        if (ObjUtil.isNotEmpty(clientId)) {
            dbServerCacheImpl.updateConnect(clientId, N);
        }
    }
}
